﻿using System.Linq;
using HashFoo.Rest.Common;
using HashFoo.Rest.CommonTests.MockResources;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace HashFoo.Rest.CommonTests
{
    [TestClass]
    public class ResourceUriCollectionBuilderTests
    {
        [TestMethod]
        [Description("Build resoure uris by picking a resource assembly")]
        public void build_from_assembly_finds_all_models()
        {
            var builder = CreateDefaultBuilder();

            var resourceUris = builder.Build();

            Assert.AreEqual(
                2,
                resourceUris.Count(r => r.ResourceType == typeof(MockResourceA) ||
                                        r.ResourceType == typeof(MockResourceB)));
        }

        [TestMethod]
        [Description("Exercises the default uri generation of a resource")]
        public void default_uris_are_generated_on_build()
        {
            var builder = CreateDefaultBuilder();
            // set to ignore any root namespace attribute
            builder.ResourceRootNamespaceAttributeFinder = assembly => null;

            var resourceUris = builder.Build();
            var uriMockA = resourceUris.GetUri<MockResourceA>();

            Assert.IsNotNull(uriMockA);
            Assert.AreEqual("rest/commontests/mockresources/mockresourcea", uriMockA);
        }

        [TestMethod]
        [Description("Builds default uri mappings, the overrides one with an explicit uri")]
        public void explicit_uris_are_used_over_defaults()
        {
            const string explicitUri = "/explicitUri";
            var builder = CreateDefaultBuilder()
                .AddExplicit(new ResourceUri { ResourceType = typeof(MockResourceA), Uri = explicitUri });

            var resourceUris = builder.Build();
            var uriMockA = resourceUris.GetUri<MockResourceA>();

            Assert.IsNotNull(uriMockA);
            Assert.AreEqual(explicitUri, uriMockA);
        }

        [TestMethod]
        [Description("Exercises the default uri generation of a resource when a prefix has been identified")]
        public void prefix_uri_is_included_if_specified()
        {
            var builder = CreateDefaultBuilder().UriPrefix("mockprefix");

            var resourceUris = builder.Build();
            var uriMockA = resourceUris.GetUri<MockResourceA>();

            Assert.IsNotNull(uriMockA);
            Assert.AreEqual("mockprefix/mockresources/mockresourcea", uriMockA);
        }

        [TestMethod]
        public void suffix_is_ignored_if_it_is_known()
        {
            var builder = CreateDefaultBuilder().AddKnownSuffix("command");

            var resourceUris = builder.Build();
            var uri = resourceUris.GetUri<ResultCommand>();

            Assert.IsNotNull(uri);
            Assert.AreEqual("mockresources/result", uri);
        }

        [TestMethod]
        public void will_not_ignore_known_suffix_if_option_is_disabled()
        {
            var builder = CreateDefaultBuilder()
                .AddKnownSuffix("command")
                .IgnoreKnownSuffix(false);

            var resourceUris = builder.Build();
            var uri = resourceUris.GetUri<ResultCommand>();

            Assert.IsNotNull(uri);
            Assert.AreEqual("mockresources/resultcommand", uri);
        }

        [TestMethod]
        public void suffix_removal_ignores_case()
        {
            var builder = CreateDefaultBuilder()
                .AddKnownSuffix("CoMmand")
                .IgnoreKnownSuffix(true);

            var resourceUris = builder.Build();
            var uri = resourceUris.GetUri<QueryMock>();

            Assert.IsNotNull(uri);
            Assert.AreEqual("mockresources/querymock", uri);
        }

        [TestMethod]
        public void can_map_resource_that_has_suffix_token_not_at_end()
        {
            var builder = CreateDefaultBuilder()
                .AddKnownSuffix("Command")
                .AddKnownSuffix("Query")
                .IgnoreKnownSuffix(true);

            var resourceUris = builder.Build();
            var uri = resourceUris.GetUri<QueryMock>();

            Assert.IsNotNull(uri);
            Assert.AreEqual("mockresources/querymock", uri);
        }


        static ResourceUriCollectionBuilder CreateDefaultBuilder()
        {
            var builder = new ResourceUriCollectionBuilder();
            builder.AddFromAssemblyOf<MockResourceA>();

            return builder;
        }
    }
}